package com.example.netty.controller;

import cn.hutool.core.util.ByteUtil;
import com.example.netty.common.client.NettyClient;
import com.example.netty.common.utils.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.nio.charset.StandardCharsets;

/**
 * <p></p>
 *
 * @author xin
 * @version 2023/11/1 17:02
 **/
@RestController
public class TestClientController {
    private static final Logger logger = LoggerFactory.getLogger(TestClientController.class);
    private final NettyClient nettyClient;

    public TestClientController(NettyClient nettyClient) {
        this.nettyClient = nettyClient;
    }

    public static void main(String[] args) {
        System.out.println("ABCDE一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;".getBytes(StandardCharsets.UTF_8).length);
    }

    @GetMapping("/app/netty/normal/byteBuf")
    public String testNormalByteBuf() throws InterruptedException {
        logger.debug("发送正常情况下的 normal byte buf 模式");
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        for (int i = 0; i < 10; i++) {
            String msg = "一岁一枯荣,野火烧不尽;";
            ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
            buffer.writeBytes(msg.getBytes(StandardCharsets.UTF_8));
            // 此处采用byte模式
            channelFuture.channel().writeAndFlush(buffer);
            Thread.sleep(1000);
        }
        nettyClient.disconnect(channelFuture.channel());
        return "normal byte buf 发送成功";
    }

    @GetMapping("/app/netty/normal/byte")
    public String testNormalByte() throws InterruptedException {
        logger.debug("发送正常情况下的 normal byte 模式");
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        for (int i = 0; i < 10; i++) {
            String msg = "一岁一枯荣,野火烧不尽;";
            // 此处发送 字节还是字符串 需要对应 NormalByteClientInitializer 里面的encoder 配置
            // 以及NormalByteServerInitializer  decoder 设置，如果不是 字节方式，则服务端收不到消息
            channelFuture.channel().writeAndFlush(msg.getBytes(StandardCharsets.UTF_8));
            Thread.sleep(1000);
        }
        nettyClient.disconnect(channelFuture.channel());
        return "normal byte 发送成功";
    }

    @GetMapping("/app/netty/normal/string")
    public String testNormalString() throws InterruptedException {
        logger.debug("发送正常情况下的  string 模式");
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        for (int i = 0; i < 10; i++) {
            String msg = "一岁一枯荣,野火烧不尽;";
            channelFuture.channel().writeAndFlush(msg);
            Thread.sleep(1000);
        }
        nettyClient.disconnect(channelFuture.channel());
        return "string 发送成功";
    }

    @GetMapping("/app/netty/normal/nbcb")
    public String testNb() throws InterruptedException {
        logger.debug("验证粘包、拆包现象，客户端给服务端发送产生拆包、服务端给客户端发送产生 粘包");
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        StringBuilder msg = new StringBuilder("一岁一枯荣,野火烧不尽;");
        for (int i = 0; i < 10; i++) {
            msg.append(msg);
        }
        msg.append("end");
        ByteBuf buffer = ByteBufAllocator.DEFAULT.buffer();
        buffer.writeBytes(msg.toString().getBytes(StandardCharsets.UTF_8));
        // 演示拆包现象，此处 只发送了一次，客户端接收了多次
        channelFuture.channel().writeAndFlush(buffer);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "string 发送成功";
    }

    @GetMapping("/app/netty/fixLength0")
    public String testFixLength0() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 此处是字节长度为 32,如果不够  32 则本次发送的消息收不到会暂存到缓存中，等凑够 32 才会监听到消息
        // 固定长度，如果长度不够且需要收到消息，通过补空格实现
        // 固定长度，如果 超过 32 则只会 收 32 长度的数据，剩余的不够 32 的暂存到缓存中，等凑够 32 才会监听到消息
        // 建议 发送的消息为 设置长度 32 的倍数，否则会将字节截断产生乱码
        // 一个汉字 3 个字节，一个, ;一个字节
        String s = "一岁一枯荣,野火烧不尽;";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/fixLength1")
    public String testFixLength1() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 此处是字节长度为 32,如果不够  32 则本次发送的消息收不到会暂存到缓存中，等凑够 32 才会监听到消息
        // 固定长度，如果长度不够且需要收到消息，通过补空格实现
        // 固定长度，如果 超过 32 则只会 收 32 长度的数据，剩余的不够 32 的暂存到缓存中，等凑够 32 才会监听到消息
        // 建议 发送的消息为 设置长度 32 的倍数，否则会将字节截断产生乱码
        // 一个汉字 3 个字节，一个, ;一个字节
        // 服务端 只能收到 一岁一枯荣,野火烧不尽;
        // 一岁一枯 需要等下一次发送的时候 凑够 32 个字节才会收到
        String s = "一岁一枯荣,野火烧不尽;一岁一枯";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        s = "一岁一枯荣,野火烧不尽;一岁一枯";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/fixLength2")
    public String testFixLength2() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 此处是字节长度为 32,如果不够  32 则本次发送的消息收不到会暂存到缓存中，等凑够 32 才会监听到消息
        // 固定长度，如果长度不够且需要收到消息，通过补空格实现
        // 固定长度，如果 超过 32 则只会 收 32 长度的数据，剩余的不够 32 的暂存到缓存中，等凑够 32 才会监听到消息
        // 建议 发送的消息为 设置长度 32 的倍数，否则会将字节截断产生乱码
        // 一个汉字 3 个字节，一个, ;一个字节
        // 服务端 只能收到 一岁一枯荣,野火烧不尽; 服务端收到  2 条消息
        //
        String s = "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/lineBase0")
    public String testLineBase0() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 服务端收不到条消息， 因为没有监听到分割符，因此服务端收不到消息
        String s = "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/lineBase1")
    public String testLineBase1() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 服务端收到一条消息
        String s = "发送一次，收到一次；一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;\r\n";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/lineBase2")
    public String testLineBase2() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 此处因为 有两个 分割符号 \r\n 因此服务端收到两条消息
        String s = "发送一次，收到两次；一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;\r\n" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;\r\n";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/delimiter0")
    public String testDelimiter0() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        // 没有分割符，服务端收不到消息
        String s = "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;没有分割符";
        //本次发送没有分割符
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        // 在发送一次
        channelFuture.channel().writeAndFlush("重新发送一次，发送分割符78B987");
        // 此处休眠 1 s 断开连接是为了收 服务端消息
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/delimiter1")
    public String testDelimiter1() throws InterruptedException {
        // 有一个分割符，服务端收到一条消息
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        String s = "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;78B987";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/delimiter2")
    public String testDelimiter2() throws InterruptedException {
        // 有两个分割符，服务端收到两条消息
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        String s = "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;78B987" +
                "一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;78B987";
        channelFuture.channel().writeAndFlush(s);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }

    @GetMapping("/app/netty/lengthField0")
    public String testLengthField0() throws InterruptedException {
        ChannelFuture channelFuture = nettyClient.connect("127.0.0.1", 9000);
        //长度 64
        byte[] sendMsgBytes = ("一岁一枯荣,野火烧不尽;一岁一枯荣,野火烧不尽;").getBytes(StandardCharsets.UTF_8);
        //长度 5
        byte[] headerBytes = "ABCDE".getBytes(StandardCharsets.UTF_8);

        int bodyLength = sendMsgBytes.length + headerBytes.length;
        byte[] bytes = {};
        //长度 5
        bytes = ByteUtils.append(bytes, headerBytes);
        //长度 4 ,设置总长度的时候 只进行 数据包长度的设置，不包含 当前长度域的长度
        bytes = ByteUtils.append(bytes, ByteUtil.intToBytes(bodyLength));
        //长度 64
        bytes = ByteUtils.append(bytes, sendMsgBytes);
        channelFuture.channel().writeAndFlush(bytes);
        Thread.sleep(1000);
        nettyClient.disconnect(channelFuture.channel());
        return "发送成功";
    }
}
